ETHERHOSTPROBE

Section: User Commands (1)
Updated: SRI Information Sciences and Technology Center
Index Return to Main Contents
 

ETHERHOSTPROBE

etherhostprobe - Ethernet Host Prober  

ORIGIN

SRI Information Sciences and Technology Center  

SYNOPSIS

etherhostprobe begin-addr end-addr  

DESCRIPTION

Probes each Internet address in the range starting with ``begin-addr'' and ending with ``end-addr'' (both ``begin-addr' and ``end-addr'' can be either hostnames or dotted-decimal Internet addresses) by forcing an ARP packet to be sent to each Internet address in the range specified. Up to 5 ARPs per hosts will be send at 0.25 second intervals. This program uses the operating system's ARP tables, and thus may degrade performance somewhat while running.

For example:

etherhostprobe 128.18.0.1 128.18.255.254
would probe the entire SRINET address space with the exception of the 128.18.0.0 and 128.18.255.255 broadcast addresses.

A list of hosts found will be sent to standard output. The format of each line is:

ethernet-addr internet-addr hostname
The ``ethernet-addr'' is the colon-separated six-octet Ethernet address of the host, the ``internet-addr'' is the dotted-decimal Internet address of the host, and the ``hostname'' is the primary name of the host as supplied by the gethostbyaddr library routine. The ``hostname'' will be omitted if the Internet address is unknown to gethostbyaddr.  

RETURN VALUE

Returns 0 if all went well, -1 if problems occurred.  

BUGS

Does not detect hosts that do not respond to ARP (either because they are down or because they are not running ARP).  

HISTORY

18-Jul-88
Written by Paul E. McKenney, SRI Information Sciences and Technology Center. RogueMonsterelse
  echo "will not overwrite ./etherhostprobe.1" fi if [ `wc -c ./etherhostprobe.1 | awk '{printf $1}'` -ne 1742 ] then echo `wc -c ./etherhostprobe.1 | awk '{print "Got " $1 ", Expected " 1742}'` fi if `test ! -s ./Makefile` then echo "writing ./Makefile" cat > ./Makefile << 'RogueMonster' ######################################################################### #                                                                       #
#       Makefile for network datagram test programs.                    #
#                                                                       #
#########################################################################

CFLAGS = -gx

BINS = etherhostprobe

all: $(BINS)

OBJS =  etherhostprobe.o        ethertoa.o      fastsleep.o     mk_udp_ncon.o   tx_arp.o        tx_hostname.o

etherhostprobe: ${OBJS}         cc -o etherhostprobe ${OBJS}

RogueMonsterelse
  echo "will not overwrite ./Makefile" fi if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 459 ] then echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 459}'` fi if `test ! -s ./etherhostprobe.c` then echo "writing ./etherhostprobe.c" cat > ./etherhostprobe.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  etherhostprobe.c                                         *

 *                                                                      *

 *      ETHERnet HOST PROBE routine.  Probes the ethernet (by forcing   *

 *      ARP's) for the specified range of IP addresses.                 *

 *      This program is unable to probe the IP address of the host on   *

 *      which it is running.                                            *

 *                                                                      *

 *      Usage:                                                          *

 *              etherhostprobe begin end                                *

 *      where `begin' is the first IP address (or host name) in the     *

 *      range to be probed, and `end' is the last IP address (or host   *

 *      name in the range to be probed.                                 *

 *                                                                      *

 *      Written 25-Nov-87 by Paul E. McKenney, SRI International.       *

 *      Copyright (c) 1987 SRI International.                           *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   etherhostprobe.c,v $

 * Revision 1.1  87/12/02  08:12:34  mckenney
 * Initial revision
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netdb.h>

/* Type definitions local to this file.                                 */

#define INCR_IP(ip_addr)        {       if ((++ip_addr.s_b4 == 0) &&     (++ip_addr.s_b3 == 0) && (++ip_addr.s_b2 == 0)) ip_addr.s_b1++; }

/* Functions exported from this file.                                   */

/* Functions local to this file.                                        */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */

main(argc, argv)

        int             argc;
        char            *argv[];

        {
        struct sockaddr_in bsa;         /* Beginning Socket Address.    */
        struct ether_addr ea;           /* Ethernet Address.            */
        char            *em;            /* Error Message pointer.       */
        struct sockaddr_in esa;         /* Ending Socket Address.       */
        int             i;
        int             retval;         /* RETurn VALue.                */
        struct sockaddr_in sa;          /* current Socket Address.      */

        /* Check command line arguments.                                */

        if (argc != 3)
                {
                fprintf(stderr, "Usage: %s begin-IP end_IP, argv[0]);
                exit(-1);
                }

        /* Translate beginning IP address into socket address struct.   */

        bzero((caddr_t)&bsa, sizeof(bsa));
        switch (tx_hostname(argv[1], &bsa, &em))
        {
        case -2:
                perror(em);
                exit(-1);
        case -1:
                fprintf(stderr, "%s", em);
                exit(-1);
        }

        /* Translate ending IP address into socket address struct.      */

        bzero((caddr_t)&esa, sizeof(esa));
        switch (tx_hostname(argv[2], &esa, &em))
        {
        case -2:
                perror(em);
                exit(-1);
        case -1:
                fprintf(stderr, "%s", em);
                exit(-1);
        }

        /* Initialize for scan loop.                                    */

        bcopy((caddr_t)&bsa, (caddr_t)&sa, sizeof(sa));

        /* Each pass through the following loop looks for one IP        */
        /* address, with up to one second delay. This means 18 hours   */
        /* to completely scan a class B network.                        */

#define SA_IP   (sa.sin_addr.S_un.S_un_b)
#define ESA_IP  (esa.sin_addr.S_un.S_un_b)
        while ((SA_IP.s_b1 < ESA_IP.s_b1) ||
         ((SA_IP.s_b1 == ESA_IP.s_b1) &&
         ((SA_IP.s_b2 < ESA_IP.s_b2) ||
         ((SA_IP.s_b2 == ESA_IP.s_b2) &&
         ((SA_IP.s_b3 < ESA_IP.s_b3) ||
         ((SA_IP.s_b3 == ESA_IP.s_b3) &&
         (SA_IP.s_b4 <= ESA_IP.s_b4)))))))
                {

                /* Initiate the arp. If this fails immediately, ditch  */
                /* and go to the next address.                          */

                if ((retval = tx_arp_init(&sa, &ea, &em)) < 0)
                        {
                        INCR_IP(SA_IP);
                        continue;
                        }

                /* If we did not get an immediate answer, wait a bit    */
                /* and check again.                                     */

                if (retval != 1)
                        for (i = 0; i < 4; i++)
                                {
                                fastsleep(0L, 250000L);
                                if ((retval = tx_arp_chk(&sa, &ea, &em)) == 1)
                                        break;
                                }

                /* If we got something, print it out.                   */

                if (retval == 1)
                        {
                        struct hostent  *hostent;
                        char            *hostname;

                        hostname = "";
                        if ((hostent = gethostbyaddr(&sa.sin_addr,
                                                 sizeof(sa.sin_addr),
                                                 AF_INET)) != NULL)
                                hostname = hostent->h_name;
                        (void)printf("%-17s %-15s %s,
                                 ethertoa(&ea),
                                 inet_ntoa(sa.sin_addr),
                                 hostname);
                        fflush(stdout);
                        }

                /* Increment to the next IP address.                    */

                INCR_IP(SA_IP);
                }

        /* When done, leave!                                            */

        exit(0);
        }
RogueMonsterelse
  echo "will not overwrite ./etherhostprobe.c" fi if [ `wc -c ./etherhostprobe.c | awk '{printf $1}'` -ne 4043 ] then echo `wc -c ./etherhostprobe.c | awk '{print "Got " $1 ", Expected " 4043}'` fi if `test ! -s ./ethertoa.c` then echo "writing ./ethertoa.c" cat > ./ethertoa.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  ethertoa.c                                               *

 *                                                                      *

 *      ETHERnet address TO Ascii (and vice versa).                     *

 *                                                                      *

 *      Written 08-Sep-87 by Paul E. McKenney, SRI International.       *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   ethertoa.c,v $

 * Revision 2.0  88/09/23  18:27:40  mckenney
 * .
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/if_ether.h>

/* Type definitions local to this file.                                 */

/* Functions exported from this file.                                   */

extern int              atoether();     /* Ascii TO ETHERnet address.   */
extern char             *ethertoa();    /* ETHERnet address TO Ascii.   */

/* Functions local to this file.                                        */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */

/* Ascii TO ETHERnet address conversion. Returns TRUE if the string    */
/* can be converted, FALSE otherwise. Address must be of form:         */
/*      xx:xx:xx:xx:xx:xx                                               */

int atoether(a, ea)

        char            *a;             /* Ascii address.               */
        struct ether_addr *ea;          /* Ethernet Address.            */

        {
        int             o0;
        int             o1;
        int             o2;
        int             o3;
        int             o4;
        int             o5;

        if (sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5) != 6)
                return (0);

        ea->ether_addr_octet[0] = o0;
        ea->ether_addr_octet[1] = o1;
        ea->ether_addr_octet[2] = o2;
        ea->ether_addr_octet[3] = o3;
        ea->ether_addr_octet[4] = o4;
        ea->ether_addr_octet[5] = o5;
        return (1);
        }
/* ETHERnet address TO Ascii conversion. Note that the returned string */
/* is kept in a static buffer, so copy it if you want to keep it!       */

extern char * ethertoa(ea)

        struct ether_addr *ea;          /* Ethernet Address.            */

        {
        static char     addr[25];       /* ascii-ized ADDRess.          */

        (void)sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x",
                 ea->ether_addr_octet[0],
                 ea->ether_addr_octet[1],
                 ea->ether_addr_octet[2],
                 ea->ether_addr_octet[3],
                 ea->ether_addr_octet[4],
                 ea->ether_addr_octet[5]);
        return (addr);
        }
RogueMonsterelse
  echo "will not overwrite ./ethertoa.c" fi if [ `wc -c ./ethertoa.c | awk '{printf $1}'` -ne 2122 ] then echo `wc -c ./ethertoa.c | awk '{print "Got " $1 ", Expected " 2122}'` fi if `test ! -s ./fastsleep.c` then echo "writing ./fastsleep.c" cat > ./fastsleep.c << 'RogueMonster' /*
 * Copyright (c) 1980 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 *
 * Hacked from sleep.c 04-Feb-87 Paul E. McKenney, SRI International
 */

#include <sys/time.h> #include <signal.h>

#define setvec(vec, a)  vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0

static int ringring;

fastsleep(n, frac)         unsigned n;
        unsigned frac;
{         int sleepx(), omask;
        struct itimerval itv, oitv;
        register struct itimerval *itp = &itv;
        struct sigvec vec, ovec;

        while (frac > 999999) {
                frac -= 1000000;
                n += 1;
        }
        if ((n == 0) &&
         (frac == 0))
                return;
        timerclear(&itp->it_interval);
        timerclear(&itp->it_value);
        if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
                return;
        itp->it_value.tv_sec = n;
        itp->it_value.tv_usec = frac;
        if (timerisset(&oitv.it_value)) {
                if (timercmp(&oitv.it_value, &itp->it_value, >)) {
                        oitv.it_value.tv_sec -= itp->it_value.tv_sec;
                        oitv.it_value.tv_usec -= itp->it_value.tv_usec;
                } else {
                        itp->it_value = oitv.it_value;
                        /*
                         * This is a hack, but we must have time to
                         * return from the setitimer after the alarm
                         * or else it'll be restarted. And, anyway,
                         * sleep never did anything more than this before.
                         */
                        oitv.it_value.tv_sec = 1;
                        oitv.it_value.tv_usec = 0;
                }
        }
        setvec(vec, sleepx);
        (void) sigvec(SIGALRM, &vec, &ovec);
        omask = sigblock(sigmask(SIGALRM));
        ringring = 0;
        (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
        while (!ringring)
                sigpause(omask &~ sigmask(SIGALRM));
        (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
        (void) sigsetmask(omask);
        (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
}

static sleepx() {

        ringring = 1;
} RogueMonsterelse
  echo "will not overwrite ./fastsleep.c" fi if [ `wc -c ./fastsleep.c | awk '{printf $1}'` -ne 1774 ] then echo `wc -c ./fastsleep.c | awk '{print "Got " $1 ", Expected " 1774}'` fi if `test ! -s ./mk_udp_ncon.c` then echo "writing ./mk_udp_ncon.c" cat > ./mk_udp_ncon.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  mk_udp_ncon.c                                            *

 *                                                                      *

 *      MaKe UDP No-CONnection socket.                                  *

 *                                                                      *

 *      Written by Paul E. McKenney, SRI International.                 *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   mk_udp_ncon.c,v $

 * Revision 2.0  88/09/23  18:28:08  mckenney
 * .
 * 
 * Revision 1.1  87/09/02  10:16:53  mckenney
 * Initial revision
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <sys/types.h> #include <sys/file.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <strings.h>

/* Type definitions local to this file.                                 */

/* Functions exported from this file.                                   */

extern int              mk_udp_ncon();  /* MaKe UDP No_CONnect. socket. */

/* Functions local to this file.                                        */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */
/* MaKe UPD No-CONnection socket. Return file descriptor of socket.    */
/* Returns -1 if there was a system call problem, points em to a string */
/* containing the system call name.                                     */
/* Returns -2 if there were other problems and points em to a           */
/* string containing a human-readable error message.                    */
/* Creates a connectionless UDP socket.                                 */

extern int mk_udp_ncon(em)

        char            **em;           /* Error Message pointer.       */

        {
        int             s;              /* Socket.                      */

        /* Create the socket, yielding a file descriptor we can do I/O  */
        /* on and connect to.                                           */

        if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
                {
                *em = "socket";
                return (-1);
                }

        return (s);
        }
RogueMonsterelse
  echo "will not overwrite ./mk_udp_ncon.c" fi if [ `wc -c ./mk_udp_ncon.c | awk '{printf $1}'` -ne 1635 ] then echo `wc -c ./mk_udp_ncon.c | awk '{print "Got " $1 ", Expected " 1635}'` fi if `test ! -s ./tx_arp.c` then echo "writing ./tx_arp.c" cat > ./tx_arp.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  tx_arp.c                                                 *

 *                                                                      *

 *      TranlateX (x is silent) ip address to ethernet address using    *

 *      Address Resolution Protocol.                                    *

 *      The most convenient routine to use is tx_arp itself, but be     *

 *      aware that it can hang (on sleep's) for several minutes waiting *

 *      for an ARP attempt to time out.  Programs that cannot wait      *

 *      that long or that can't spare SIGALRM should use the routines:  *

 *              tx_arp_init     to start the arp.                       *

 *              tx_arp_chk      to check on its progress.               *

 *              tx_arp_wait     to hang waiting for the arp to complete.*

 *                              (uses SIGALRM).                         *

 *                                                                      *

 *      Written 08-Sep-87 by Paul E. McKenney, SRI International.       *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   tx_arp.c,v $

 * Revision 2.0  88/09/23  18:28:23  mckenney
 * .
 * 
 * Revision 1.2  88/09/19  09:15:37  mckenney
 * Added tx_arp_perm and tx_arp_tmp routines
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <signal.h>

/* Type definitions local to this file.                                 */

/* Functions exported from this file.                                   */

extern int              tx_arp();               /* TX using ARP.        */
extern int              tx_arp_chk();           /* TX ARP CHecK.        */
extern int              tx_arp_init();          /* TX ARP INITiate.     */
extern int              tx_arp_perm();          /* make entry PERManent.*/
extern int              tx_arp_tmp();           /* make entry TeMPorary.*/
extern int              tx_arp_wait();          /* TX ARP WAIT for done.*/

/* Functions local to this file.                                        */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */

/* TranslateX using Address Resolution Protocol. Internet address      */
/* (in the form of a sockaddr_in *) is passed in through sa, puts       */
/* resulting ethernet address into ea. Returns 0 if all went well,     */
/* -1 if a system call failed (em is pointed to the name of the system  */
/* call in this case).                                                  */
/* Note that no arp will actually be transmitted if the address is      */
/* already in the cache.                                                */

extern int tx_arp(sa, ea, em)

        struct sockaddr_in *sa;         /* Socket Address.              */
        struct ether_addr *ea;          /* Ethernet Address.            */
        char            **em;           /* Error Message pointer.       */

        {
        int             retval;         /* RETurn VALue.                */

        /* Initiate the arp. If this succeeds immediately (because the */
        /* arp was already cached), just return.                        */

        if ((retval = tx_arp_init(sa, ea, em)) < 0)
                return (retval);
        if (retval == 1)
                return (0);

        /* Wait for the arp to complete.                                */

        while ((retval = tx_arp_wait(sa, ea, em)) == 0)
                sleep(1);
        return (retval);
        }
/* TranslateX using ARP, CHecK results. Internet address               */
/* (in the form of a sockaddr_in *) is passed in through sa, puts       */
/* resulting ethernet address into ea. Returns 1 if the desired entry  */
/* is in the cache, 0 if the arp is in process, and -1 if a system call */
/* failed (em is pointed to the name of the system call in this case).  */

extern int tx_arp_chk(sa, ea, em)

        struct sockaddr_in *sa;         /* Socket Address.              */
        struct ether_addr *ea;          /* Ethernet Address.            */
        char            **em;           /* Error Message pointer.       */

        {
        static struct arpreq arpreq;    /* ARP REQuest structure.       */
        int             s;              /* Socket file descriptor.      */

        /* Set up arp request struct.                                   */

        bzero((caddr_t)&arpreq, sizeof(arpreq));
        bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));

        arpreq.arp_pa.sa_family = AF_INET;
        arpreq.arp_ha.sa_family = AF_UNSPEC;

        /* Open a socket to do ioctls on (just to arp!).                */


        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                {
                *em = "socket";
                return (-1);
                }
          /* Do the ioctl, check the result.                              */

        if (ioctl(s, SIOCGARP, (caddr_t)&arpreq) == -1)
                {
                *em = "ioctl SIOCGARP";
                close(s);
                return (-1);
                }

        close(s);
        (void)bcopy(arpreq.arp_ha.sa_data, ea, sizeof(struct ether_addr));
        return ((arpreq.arp_flags & ATF_COM) != 0);
        }
/* TranslateX using ARP, INITiate process. Internet address            */
/* (in the form of a sockaddr_in *) is passed in through sa, puts       */
/* resulting ethernet address into ea. Returns 1 if the desired entry  */
/* is already in the cache, 0 if the arp is in process, and -1 if a     */
/* system call failed (em is pointed to the name of the system call in  */
/* this case).                                                          */

int tx_arp_init(sa, ea, em)

        struct sockaddr_in *sa;         /* Socket Address.              */
        struct ether_addr *ea;          /* Ethernet Address.            */
        char            **em;           /* Error Message pointer.       */

        {
        static struct arpreq arpreq;
        int             discard = -1;
        int             (*oldsig)();
        int             retval;
        int             s = -1;

        /* Set up arp request struct.                                   */

        bzero((caddr_t)&arpreq, sizeof(arpreq));
        bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));

        arpreq.arp_pa.sa_family = AF_INET;
        arpreq.arp_ha.sa_family = AF_UNSPEC;

        /* Get a socket suitable for arp'ing.                           */


        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                {                 *em = "socket";
                retval = -1;
                goto cleanup;

                }

        /* Check to see if it is already in cache.                      */

        if ((ioctl(s, SIOCGARP, (caddr_t)&arpreq) != -1) &&

            ((arpreq.arp_flags & ATF_COM) != 0))                 {
                (void)bcopy(arpreq.arp_ha.sa_data, ea,
                         sizeof(struct ether_addr));
                retval = 1;
                goto cleanup;
                }

        /* Send a udp packet to force the system to send an arp. We    */
        /* send to the echo port to minimize impact on the net.         */
        /* Note that we could use an NIT socket for this, but that      */
        /* would require super-user privileges.                         */

        if ((discard = mk_udp_ncon(em)) < 0)
                {
                retval = discard;
                goto cleanup;
                }
        oldsig = signal(SIGPIPE, SIG_IGN);
        sa->sin_family = AF_INET;
        sa->sin_port = IPPORT_ECHO;
        if (sendto(discard, "abcd", 5, 0, sa, sizeof(*sa)) != 5)
                {
                *em = "sendto";
                retval = -1;
                goto cleanup;
                }
        (void)signal(SIGPIPE, oldsig);

        /* Check cache again just in case . . .                         */

        if (ioctl(s, SIOCGARP, (caddr_t)&arpreq) == -1)
                {
                *em = "ioctl SIOCGARP";
                retval = -1;
                goto cleanup;
                }

        if ((arpreq.arp_flags & ATF_COM) != 0)                 {
                (void)bcopy(arpreq.arp_ha.sa_data, ea,
                         sizeof(struct ether_addr));
                retval = 1;
                goto cleanup;
                }
        retval = 0;

cleanup:

        /* Close file descriptors.                                      */

        if (s != -1)
                close(s);
        if (discard != -1)
                close(discard);
        return (retval);
        }
/* TranslateX using ARP, force existing entry to be PERManent.          */
/* Internet address (in the form of a sockaddr_in *) is passed in       */
/* through sa, ethernet address (in the form of a struct ether_addr)    */
/* is optionally passed through ea (if ea is NULL, the address will     */
/* be looked up in the arp cache). Returns 1 if the desired entry      */
/* has been cached, 0 if the arp is in process, and -1 if a system call */
/* failed (em is pointed to the name of the system call in this case).  */

extern int tx_arp_perm(sa, ea, em)

        struct sockaddr_in *sa;         /* Socket Address.              */
        struct ether_addr *ea;          /* Ethernet Address.            */
        char            **em;           /* Error Message pointer.       */

        {
        static struct arpreq arpreq;    /* ARP REQuest structure.       */
        int             retval;         /* RETurn VALue.                */
        int             s;              /* Socket file descriptor.      */

        /* Set up arp request struct.                                   */

        bzero((caddr_t)&arpreq, sizeof(arpreq));
        bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));

        arpreq.arp_pa.sa_family = AF_INET;
        arpreq.arp_ha.sa_family = AF_UNSPEC;

        /* Open a socket to do ioctls on (just to arp!).                */


        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                {
                *em = "socket";
                return (-1);
                }
          /* Do the ioctl, check the result.                              */

        if (((retval = ioctl(s, SIOCGARP, (caddr_t)&arpreq)) == -1) &&
         (ea == NULL))
                {
                *em = "ioctl SIOCGARP";
                close(s);
                return (-1);
                }
        if ((retval != -1) &&
         ((arpreq.arp_flags & ATF_COM) == 0))
                {
                close(s);
                return (0);
                }

        /* Set the ethernet address if requested, mark the entry        */
        /* permanent.                                                   */

        if (ea != NULL)
                (void)bcopy(ea, (caddr_t)arpreq.arp_ha.sa_data, sizeof(*ea));
        arpreq.arp_flags |= ATF_PERM;

          /* Delete the existing entry.                                   */

        /* if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) == -1)
                {
                *em = "ioctl SIOCDARP";
                close(s);
                return (-1);
                }
        */

        /* Do the ioctl, check the result.                              */

        if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) == -1)
                {
                *em = "ioctl SIOCSARP";
                close(s);
                return (-1);
                }
        close(s);
        return (1);
        }
/* TranslateX using ARP, force existing entry to be TeMPorary.          */
/* Internet address (in the form of a sockaddr_in *) is passed in       */
/* through sa, ethernet address (in the form of a struct ether_addr)    */
/* is optionally passed through ea (if ea is NULL, the address will     */
/* be looked up in the arp cache). Returns 1 if the desired entry      */
/* has been cached, 0 if the arp is in process, and -1 if a system call */
/* failed (em is pointed to the name of the system call in this case).  */

extern int tx_arp_tmp(sa, ea, em)

        struct sockaddr_in *sa;         /* Socket Address.              */
        struct ether_addr *ea;          /* Ethernet Address.            */
        char            **em;           /* Error Message pointer.       */

        {
        static struct arpreq arpreq;    /* ARP REQuest structure.       */
        int             retval;         /* RETurn VALue.                */
        int             s;              /* Socket file descriptor.      */

        /* Set up arp request struct.                                   */

        bzero((caddr_t)&arpreq, sizeof(arpreq));
        bcopy(sa, (caddr_t)&arpreq.arp_pa, sizeof(*sa));

        arpreq.arp_pa.sa_family = AF_INET;
        arpreq.arp_ha.sa_family = AF_UNSPEC;

        /* Open a socket to do ioctls on (just to arp!).                */


        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
                {
                *em = "socket";
                return (-1);
                }
          /* Do the ioctl, check the result.                              */

        if (((retval = ioctl(s, SIOCGARP, (caddr_t)&arpreq)) == -1) &&
         (ea == NULL))
                {
                *em = "ioctl SIOCGARP";
                close(s);
                return (-1);
                }
        if ((retval != -1) &&
         ((arpreq.arp_flags & ATF_COM) == 0))
                {
                close(s);
                return (0);
                }

        /* Set the ethernet address if requested, mark the entry        */
        /* permanent.                                                   */

        if (ea != NULL)
                (void)bcopy(ea, (caddr_t)arpreq.arp_ha.sa_data, sizeof(*ea));
        arpreq.arp_flags &= ~ATF_PERM;

          /* Delete the existing entry.                                   */

        /* if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) == -1)
                {
                *em = "ioctl SIOCDARP";
                close(s);
                return (-1);
                }
        */

        /* Do the ioctl, check the result.                              */

        if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) == -1)
                {
                *em = "ioctl SIOCSARP";
                close(s);
                return (-1);
                }
        close(s);
        return (1);
        }
/* TranslateX using ARP, WAIT for completion. Internet address         */
/* (in the form of a sockaddr_in *) is passed in through sa, puts       */
/* resulting ethernet address into ea. Returns 1 all went well, and -1 */
/* if a system call failed (em is pointed to the name of the system     */
/* call in this case). Note that this routine can hang for several     */
/* minutes while the system waits for an arp response, and that this    */
/* routine (indirectly) uses SIGALRM.                                   */

int tx_arp_wait(sa, ea, em)

        struct sockaddr_in *sa;         /* Socket Address.              */
        struct ether_addr *ea;          /* Ethernet Address.            */
        char            **em;           /* Error Message pointer.       */

        {
        int             retval;

        /* check status until we get a definite answer.                 */

        while ((retval = tx_arp_chk(sa, ea, em)) == 0)
                sleep(1);
        return (retval);
        }
RogueMonsterelse
  echo "will not overwrite ./tx_arp.c" fi if [ `wc -c ./tx_arp.c | awk '{printf $1}'` -ne 11372 ] then echo `wc -c ./tx_arp.c | awk '{print "Got " $1 ", Expected " 11372}'` fi if `test ! -s ./tx_hostname.c` then echo "writing ./tx_hostname.c" cat > ./tx_hostname.c << 'RogueMonster' /************************************************************************
 *                                                                      *

 *      File:  tx_hostname.c                                            *

 *                                                                      *

 *      TranslateX HOSTNAME to internet address.                        *

 *                                                                      *

 *      Written by Paul E. McKenney, SRI International.                 *

 *                                                                      *

 ************************************************************************/

/*
 *      $Log:   tx_hostname.c,v $

 * Revision 2.0  88/09/23  18:28:31  mckenney
 * .
 * 
 */

/* Include files.                                                       */

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <strings.h>

/* Type definitions local to this file.                                 */

/* Functions exported from this file.                                   */

extern int              tx_hostname();  /* TranslateX HOSTNAME.         */

/* Functions local to this file.                                        */

/* Variables exported from this file.                                   */

/* Variables local to this file.                                        */
/* TranslateX HOSTNAME to internet address (the 'X' is silent).         */
/* Returns -1 if there was a system call problem, points em to a string */
/* containing the system call name.                                     */
/* Returns -2 if there were other problems and points em to a           */
/* string containing a human-readable error message.                    */
/* Returns host address in sa.                                          */

extern int tx_hostname(host, sa, em)

        char            *host;          /* HOST name or id.             */
        struct sockaddr_in *sa;         /* Socket Address.              */
        char            **em;           /* Error Message pointer.       */

        {
        char            errmsg[BUFSIZ]; /* ERRor MeSsaGe buffer.        */
        struct hostent  *hp;            /* Host entry Pointer.          */
        char            *rerrmsg;       /* Regex ERRor MeSsaGe.         */

        char            *re_comp();     /* regex library routines. No   */
        int             re_exec();      /* include files!!!!!!          */

        /* Initialize socket address.                                   */

        bzero((char *)sa, sizeof(*sa));
        sa->sin_family = AF_INET;

        /* Get host name -- check for internet address.                 */

        if ((rerrmsg =
         re_comp("[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"))
         !=
         (char *)0)
                {
                sprintf(errmsg, "re_comp error: %s, rerrmsg);
                *em = errmsg;
                return (-2);
                }
        if (re_exec(host) == 1)
                {
                u_long          inet_addr();    /* Kludge around C bug. */

                sa->sin_addr.s_addr = inet_addr(host);
                }
        else if ((hp = gethostbyname(host)) == NULL)
                {
                sprintf(errmsg, "               *em = errmsg;
                return (-2);
                }
        else
                sa->sin_addr.s_addr = *(u_long *)hp->h_addr;

        return (0);
        }
RogueMonsterelse
  echo "will not overwrite ./tx_hostname.c" fi if [ `wc -c ./tx_hostname.c | awk '{printf $1}'` -ne 2332 ] then echo `wc -c ./tx_hostname.c | awk '{print "Got " $1 ", Expected " 2332}'` fi echo "Finished archive 1 of 1" exit


 

Index

ETHERHOSTPROBE
ORIGIN
SYNOPSIS
DESCRIPTION
RETURN VALUE
BUGS
HISTORY

This document was created by man2html, using the manual pages.
Time: 11:58:38 GMT, November 04, 2024